﻿package core.drawing
{
    import core.enum.*;
    import core.ui.*;
    import core.ui.controls.*;
    import flash.display.*;
    import flash.events.*;
    import flash.geom.*;

    final public class CloneTool extends ShapeTool
    {
        private var mark:Point;
        private var soffset:Point;
        private var source:BitmapData;
        var n:int;
        var cx:int;
        var cy:int;
        var sx:int;
        var sy:int;
        var alpha:int;
        var a:int;
        var r:int;
        var g:int;
        var b:int;
        var ta:int;
        var tr:int;
        var tg:int;
        var tb:int;
        var px:uint;
        var pt:uint;
        var f:Number;
        var tf:Number;
        var oa:int;
        var na:int;
        var ba:int;

        public function CloneTool(param1:Tuyitu)
        {
            super(param1, ToolType.Clone);
            param1.stage.addEventListener(KeyboardEvent.KEY_DOWN, this.KeyDown, false, 0, true);
            param1.stage.addEventListener(KeyboardEvent.KEY_UP, this.KeyUp, false, 0, true);
            return;
        }// end function

        override public function MouseDown(event:MouseEvent) : void
        {
            if (!type.attitude.locked)
            {
                this.UpdateReferences();
                if (event.ctrlKey)
                {
                    if (ed.marker == null)
                    {
                        ed.marker = new Marker();
                        ed.addChildAt(ed.marker, 4);
                    }
                    ed.marker.SetOrigin(canvas.GetMousePosition());
                }
                else if (ed.marker != null)
                {
                    this.source = options.all ? (canvas.screenshot) : (layer.activeBitmap);
                    this.soffset = options.all ? (new Point(0, 0)) : (layer.offset);
                    this.Prepare(Action.CloneTool, layer.SetBitmapEditMode(options.opacity, canvas.clip));
                    if (ed.marker.offset == null || !options.aligned)
                    {
                        ed.marker.SetOffset(canvas.GetMousePosition());
                    }
                    ed.marker.visible = true;
                    if (!event.shiftKey)
                    {
                        var _loc_2:int = -1;
                        y = -1;
                        x = _loc_2;
                    }
                    this.MouseDrag(null);
                }
                else
                {
                    new AlertDialog(ed, U.RM("rm_clone_not_defined"));
                }
            }
            return;
        }// end function

        override public function KeyDown(event:KeyboardEvent) : void
        {
            var _loc_2:* = undefined;
            if (event.keyCode == 190 || event.keyCode == 188)
            {
                _loc_2 = event.shiftKey ? (event.keyCode + 100) : (event.keyCode);
                ed.options.selected.bp.SetShapeProperty(_loc_2);
                if (AppState.OnCanvas)
                {
                    ed.cursor.Set(type);
                }
            }
            else if (event.keyCode == 17)
            {
                ed.cursor.Set(ToolType.CloneMarker, Boolean(ed.cursor.freeze || AppState.OnCanvas));
            }
            return;
        }// end function

        public function KeyUp(event:KeyboardEvent) : void
        {
            if (!event.ctrlKey)
            {
                ed.cursor.Set(ToolType.Clone, Boolean(ed.cursor.freeze || AppState.OnCanvas));
            }
            return;
        }// end function

        override public function CleanUp() : void
        {
            ed.stage.removeEventListener(KeyboardEvent.KEY_DOWN, this.KeyDown, false);
            ed.stage.removeEventListener(KeyboardEvent.KEY_UP, this.KeyUp, false);
            return;
        }// end function

        override public function MouseDrag(event:MouseEvent) : void
        {
            ed.marker.Trace(canvas.zoomlevel);
            if (target != null)
            {
                p = canvas.GetOffsetMousePosition(offset);
                target.lock();
                if (x == -1)
                {
                    lx = p.x;
                    ly = p.y;
                    x = p.x;
                    y = p.y;
                    this.DrawShape(x, y);
                }
                if (p.x != x || p.y != y)
                {
                    dx = p.x - x;
                    dy = p.y - y;
                    xinc = dx > 0 ? (1) : (-1);
                    yinc = dy > 0 ? (1) : (-1);
                    dx = dx < 0 ? (-dx) : (dx);
                    dy = dy < 0 ? (-dy) : (dy);
                    if (dx > dy)
                    {
                        cumul = dx * 0.5;
                        i = 1;
                        while (i <= dx)
                        {
                            
                            x = x + xinc;
                            cumul = cumul + dy;
                            if (cumul >= dx)
                            {
                                cumul = cumul - dx;
                                y = y + yinc;
                            }
                            if (x > lx + shape.step || x < lx - shape.step || y > ly + shape.step || y < ly - shape.step)
                            {
                                lx = x;
                                ly = y;
                                this.DrawShape(x, y);
                            }
                            var _loc_3:* = i + 1;
                            i = _loc_3;
                        }
                    }
                    else
                    {
                        cumul = dy * 0.5;
                        i = 1;
                        while (i <= dy)
                        {
                            
                            y = y + yinc;
                            cumul = cumul + dx;
                            if (cumul >= dy)
                            {
                                cumul = cumul - dy;
                                x = x + xinc;
                            }
                            if (x > lx + shape.step || x < lx - shape.step || y > ly + shape.step || y < ly - shape.step)
                            {
                                lx = x;
                                ly = y;
                                this.DrawShape(x, y);
                            }
                            var _loc_3:* = i + 1;
                            i = _loc_3;
                        }
                    }
                }
                target.unlock();
            }
            return;
        }// end function

        override public function MouseUp(event:MouseEvent) : void
        {
            ed.cursor.freeze = false;
            ed.removeEventListener(MouseEvent.MOUSE_MOVE, this.MouseDrag, false);
            ed.removeEventListener(MouseEvent.MOUSE_UP, this.MouseUp, false);
            layer.RemoveBitmapEditMode();
            canvas.UpdateAfterEdit();
            history.Commit();
            ed.marker.visible = false;
            if (!AppState.OnCanvas)
            {
                ed.cursor.Set(ToolType.None);
            }
            return;
        }// end function

        override public function DrawShape(soffset:int, soffset:int) : void
        {
            this.n = 0;
            this.sy = soffset - int(shape.height * 0.5);
            this.cy = this.sy + shape.height;
            while (this.sy < this.cy)
            {
                
                this.sx = soffset - int(shape.width * 0.5);
                this.cx = this.sx + shape.width;
                while (this.sx < this.cx)
                {
                    
                    this.alpha = shape.data[this.n];
                    if (this.alpha > 0 && (selection == null || selection.IsSelected(this.sx + offset.x, this.sy + offset.y)))
                    {
                        this.px = this.source.getPixel32(this.sx + offset.x + ed.marker.offset.x - this.soffset.x, this.sy + offset.y + ed.marker.offset.y - this.soffset.y);
                        this.oa = this.px >>> 24 & 255;
                        this.ta = int(this.oa * (this.alpha / 255));
                        if (this.ta > 0)
                        {
                            this.tr = this.px >>> 16 & 255;
                            this.tg = this.px >>> 8 & 255;
                            this.tb = this.px & 255;
                            if (this.ta < 255)
                            {
                                this.px = target.getPixel32(this.sx, this.sy);
                                var _loc_3:* = this.px >>> 24 & 255;
                                this.ba = this.px >>> 24 & 255;
                                this.a = _loc_3;
                                if (this.a > 0)
                                {
                                    this.r = this.px >>> 16 & 255;
                                    this.g = this.px >>> 8 & 255;
                                    this.b = this.px & 255;
                                    this.ta = this.ta + (255 - this.ta) * this.a / 255;
                                    if (this.ta > 255)
                                    {
                                        this.ta = 255;
                                    }
                                    this.tf = this.alpha / this.ta;
                                    this.f = 1 - this.tf;
                                    this.tr = this.r * this.f + this.tr * this.tf;
                                    this.tg = this.g * this.f + this.tg * this.tf;
                                    this.tb = this.b * this.f + this.tb * this.tf;
                                    if (this.a < 255)
                                    {
                                        this.px = target.getPixel32(this.sx, this.sy);
                                        this.na = this.px >>> 24 & 255;
                                        this.oa = this.oa + (255 - this.alpha) * this.na / 255;
                                        if (this.oa > 255)
                                        {
                                            this.oa = 255;
                                        }
                                        if (this.ta > this.oa)
                                        {
                                            this.ta = this.oa;
                                        }
                                    }
                                    else
                                    {
                                        this.ba = this.ta;
                                    }
                                    if (this.ta >= this.ba)
                                    {
                                        this.pt = this.ta << 24 | this.tr << 16 | this.tg << 8 | this.tb;
                                        if (this.pt != this.px)
                                        {
                                            target.setPixel32(this.sx, this.sy, this.pt);
                                        }
                                    }
                                }
                                else
                                {
                                    this.pt = this.ta << 24 | this.tr << 16 | this.tg << 8 | this.tb;
                                    if (this.pt != this.px)
                                    {
                                        target.setPixel32(this.sx, this.sy, this.pt);
                                    }
                                }
                            }
                            else
                            {
                                target.setPixel32(this.sx, this.sy, this.ta << 24 | this.tr << 16 | this.tg << 8 | this.tb);
                            }
                        }
                    }
                    var _loc_3:String = this;
                    var _loc_4:* = this.n + 1;
                    _loc_3.n = _loc_4;
                    var _loc_3:String = this;
                    var _loc_4:* = this.sx + 1;
                    _loc_3.sx = _loc_4;
                }
                var _loc_3:String = this;
                var _loc_4:* = this.sy + 1;
                _loc_3.sy = _loc_4;
            }
            return;
        }// end function

    }
}
